// A星算法
let EMPTY   = 0; //空的格子
let OBSTACLE= 1; //障碍格子
function createCell(x,y,g,h,f,father){
    let obj = new Object();
    obj.x = x;
    obj.y = y;
    obj.g = g;
    obj.h = h;
    obj.f = f;
	obj.father = father;
    return obj;
};

function heapComparef(x,y){
    return x.f - y.f;
};
// 邻边六个方向的位置坐标
var direction0 =[[1,0],[1,1],[0,-1],[0,1],[-1,0],[-1,1]]; // 偶数
var direction1 =[[1,-1],[1,0],[0,-1],[0,1],[-1,-1],[-1,0]];//奇数

function judge(x,y,x1,y1){
    return (10 * (Math.abs(x1 - x) + Math.abs(y1 - y)));
};
function maxValue(x,y,x1,y1){
    return (10 * (Math.abs(x1 - x) * Math.abs(y1 - y)));
}

function AILogic() {
	this.steps =  0;
	return this;
};
AILogic.prototype.init = function() {
    let estiVal      =  judge(this.startX,this.startY,this.endX,this.endY);
    this.startNode   = createCell(this.startX,this.startY,0,estiVal,estiVal,null);
    this.endNode     = createCell(this.endX,this.endY,0,0,0,null);
    this.openTable   = new Array();
    this.closedTable = new Array();
    this.findOver    = false;
    this.bFind       = false;
    this.steps       =  0;
    this.maxF        = maxValue(this.startX,this.startY,this.endX,this.endY);
    this.openTable.push(this.startNode);
};

//初始化地图数据 --- 猫的位置catpos
AILogic.prototype.initMap = function(catPos,map,rows,cols,edges) {
    this.maze = map;//地图数据
    this.edge = [] ;//边缘格子
    if(edges){
        for (var i = 0; i < edges.length; i++) {
            let e = edges[i];
            if(this.maze[e.row][e.col]==0){//边缘格子是否被占领
                var data ={x:e.row,y:e.col,f:0};
                this.edge.push(data);
            }
        }
    }else{
        for ( var i = 0; i < rows; ++i ){

            for ( var j = 0; j < cols; ++j ){
                if(i==0||i==rows-1||j==0||j==cols-1){

                    if(this.maze[i][j]==0){//边缘格子是否被占领
                        var data ={x:i,y:j,f:0};
                        this.edge.push(data);
                    }
                }
            }
        }
    }

    this.rows   = rows;
    this.cols   = cols;
    this.startX = Math.floor(catPos/cols);//猫的坐标
    this.startY = catPos%cols;//
};

//判断某一格子是否能通过
AILogic.prototype.isInMap = function(x,y){
    if( x >= 0 && x < this.rows &&
        y >= 0 && y < this.cols && 
        (this.maze[x][y] ==0)
    ) {return true;}
    return false;
}

//寻路
AILogic.prototype.pathFinding = function(){
    let tempNode = null;
    //while (true) {
        //猫被围死
        if (this.openTable.length ==0){//判断OPEN表是否为空
            this.findOver = true;
            return false;
        }

        tempNode = this.openTable.shift();
        if (tempNode.x == this.endX && tempNode.y == this.endY){
        //找到路径  
            this.endNode.g = tempNode.g;
            this.endNode.h = tempNode.h;
            this.endNode.f = tempNode.f;
            this.endNode.father = tempNode.father;
            this.findOver = true;
            this.bFind = true;
            return true;
        }
        //六个相邻位置
        var dir = direction0;
        if(tempNode.x%2==0){
            dir = direction1;
        }
        for (let i=0;i<6;i++){//-针对每个子节点 
            let nextX = tempNode.x + dir[i][0];
            let nextY = tempNode.y + dir[i][1];  
            if (this.isInMap(nextX,nextY)){
                let newGVal = tempNode.g + 10; 
                let openTableResult = null; 
                let iOpenResult = 0;
                for (let k = 0; k <this.openTable.length ; k++) {
                	if(this.openTable[k].x==nextX && this.openTable[k].y == nextY){
						openTableResult = this.openTable[k];  
                        iOpenResult = k;
                        break;
                	}
                }                
                if (openTableResult != null && openTableResult.g <= newGVal){
                	continue;
                }              
                let closedTableResult = null;
                let iClosedResult = 0;
                for (let k = 0; k < this.closedTable.length; k++) {
                	if(this.closedTable[k].x==nextX && this.closedTable[k].y == nextY){
						closedTableResult = this.closedTable[k];  
                        iClosedResult = k;
                        break;
                	}
                }
                if(closedTableResult != null && closedTableResult.g <= newGVal){                 
                    continue ;                
                }
                let bestNode = new Object();
                bestNode.x = nextX;
                bestNode.y = nextY;
                bestNode.father = tempNode;
                bestNode.g = newGVal;
                bestNode.h = judge(nextX,nextY,this.endX,this.endY);
                bestNode.f = bestNode.g + bestNode.h;
                if(closedTableResult != null ){
                	this.closedTable.splice(iClosedResult,1);
                    closedTableResult = null;
                } 
                
                //如果已经存在于OPEN表，更新
                if(openTableResult != null){
                	this.openTable.splice(iOpenResult,1);
                	//this.openTable.sort(heapComparef);
                    openTableResult = null;
                }
                //this.openTable.push(bestNode);//将最优节点放入OPEN表
                //this.openTable.sort(heapComparef);//重新排序
                let index = this.openTable.length;
                for (let t = 0; t < this.openTable.length; t++) {
                    if(bestNode.f<this.openTable[t].f){
                        index = t;
                        break;
                    }
                }
                this.openTable.splice(index,0,bestNode); 
            }
        }
        this.closedTable.push(tempNode);
        
    //}

    this.steps = this.steps +1;
    return false;
};
//生成路径信息
AILogic.prototype.generatePath = function(cell){
	var path =new Array();
    let nodeChild = this.endNode;
    while (!(nodeChild.x == this.startNode.x && nodeChild.y == this.startNode.y) ){
        let obj = new Object();
    	obj.x = nodeChild.x;
    	obj.y = nodeChild.y;
    	path.push(obj);
        nodeChild = nodeChild.father;
    }
    path.reverse();
    cell.path = path;
};
//
AILogic.prototype.getCellIdx = function(x,y){
    var cells =this.edge;
    for (var i = 0; i < cells.length; i++) {
        let cell = cells[i];
        if(x== cell.x && y== cell.y){
            return i;
        }
    }
};
//打印路径信息
AILogic.prototype.logPath = function(data){
    let str =""
    for (var i = 0; i < data.path.length; i++) {
    	let path = data.path[i];
    	str = str +"("+path.x+","+path.y+")->"
    }
    str = str+"步数："  + data.path.length +'\n'
    console.log(str);
};
//清空数据
AILogic.prototype.clear = function(){
	this.openTable.splice(0,this.openTable.length);
	this.closedTable.splice(0,this.closedTable.length);
};

AILogic.prototype.isOver = function(){
    return this.findOver;
};
//寻路
AILogic.prototype.beginSearch = function(data){
    this.endX = data.x;
    this.endY = data.y;
    this.init();
    while(!this.findOver) {
        this.pathFinding();
    }
    if(this.bFind){
        this.generatePath(data);
        //this.logPath(data);
    }
    this.clear();
};
//是否是边缘
AILogic.prototype.isBoard = function(x,y){
    if(x==0||y==0||x==this.rows-1||y==this.cols-1){
        return true;
    }
    return false;
}

//6个方向的格子
AILogic.prototype.getNeighbors = function(x,y){
    var neighbors = [];
    var dir = direction0;
    if(x%2==0){
        dir = direction1;
    }
    for (let i=0;i<6;i++){//-针对每个子节点 
        let nextX = x + dir[i][0];
        let nextY = y + dir[i][1];  
        if (this.isInMap(nextX,nextY)){
            neighbors.push({x:nextX,y:nextY});
        }
    }
    return neighbors;
}

//计算能走格子的权重 ：越大表示越难围住
var calculVal = function(dep){
    return Math.pow(2,20)/Math.pow(2,dep);
}
//查找最佳的邻边格子 level:难度 1-2-3
var Eazy  = 1;
var Normal= 2;
var Hard  = 3;
AILogic.prototype.findBestCell = function(level){
    var edge = this.edge;
    var i=0;
    //1- 查找到边缘的路径
    for (i = 0; i < edge.length; i++) {
        var data = edge[i];
        if(data.path){
            this.logPath(data);
        }else if(this.maze[data.x][data.y]==0){
            this.beginSearch(data);
        }
    }
    ///////2 计算邻居格子value
    var neighbor = [];
    function getNeighborCell(x,y){
        var temp = null;
        for (let k = 0; k < neighbor.length; k++) {
            var cell = neighbor[k];
            if(cell.x==x && cell.y ==y){
                temp = cell 
                break;
            }
        }
        if(temp){
            
        }else{
            temp = {x:x,y:y,f:0};
            neighbor.push(temp);
        }
        return temp;
    }
    for (i = 0; i < edge.length; i++) {
        var data = edge[i];
        if(this.maze[data.x][data.y]==0){
            var path = data.path;
            if(path && path.length>0){
                var cell = getNeighborCell(path[0].x,path[0].y);
                cell.f  = cell.f + calculVal(path.length);
            }
        }  
    }
    // 3-- 判断小猫是否被围住
    // result -- 0：没有被围住 1：被围住了，但是还可以移动 2：不能移动了
    if(neighbor.length==0){
        ////已经围死但是小猫还可以走
        var neighCells = this.getNeighbors(this.startX,this.startY);
        if(neighCells.length==0){
            //--小猫不能走了
            return {result:2,cell:null};
        }else{
            let idx = Math.floor(Math.random()*neighCells.length);

            return {result:1,cell:neighCells[idx]};
        }
    }
    if(Eazy == level){
        let id = Math.floor(Math.random()*neighbor.length);
        return { result:0,cell:neighbor[id] } ;
    } 
    neighbor.sort(heapComparef);
    // ////////////打印相邻6个格子的值
    // let str ="calculVal: "
    // for (i = 0; i < neighbor.length; i++) {
    //     let cell = neighbor[i];
    //     str = str +"("+cell.x+","+cell.y+")->"+cell.f+";    "
    // }
    // console.log(str);

    if(Normal == level){
        let id = Math.floor(neighbor.length/2+Math.random()*neighbor.length/2);
        if(id>neighbor.length){
            id = neighbor.length-1;
        }
        console.log("getNext Direction",id,neighbor[id]);
        return { result:0,cell:neighbor[id] } ;
    }
    return {result:0,cell:neighbor.pop()};
};

//查找下一步可走格子
function getNextDirection(catPos, map,rows,cols,level,edges){
    let logic = new AILogic();
    //初始化地图数据
    logic.initMap(catPos, map,rows,cols,edges);
    //查找最佳格子
    let cell = logic.findBestCell(level);
    return cell;
}


// console.log('获取当前直播间贵宾数据')
// hyExt.context.getVip().then(vipList => {
//   console.log('获取当前直播间贵宾数据成功，返回：' + JSON.stringify(vipList))    
// }).catch(err => {
//   console.log('获取当前直播间贵宾数据失败，错误信息：' + err.message)
// })

// hyExt.env.getVersionType().then(versionInfo => {
//   console.log('获取当前小程序版本信息成功，返回：' + JSON.stringify(versionInfo))    
// }).catch(err => {
//   console.log('获取当前小程序版本信息失败，错误信息：' + err.message)
// })

// hyExt.context.getUserInfo().then(userInfo => {
//   console.log('获取当前用户（观众/主播）信息成功，返回：' + JSON.stringify(userInfo))    
// }).catch(err => {
//   console.log('获取当前用户（观众/主播）信息失败，错误信息：' + err.message)
// })

// hyExt.context.getStreamerInfo().then(streamerInfo => {
//   console.log('获取当前直播间主播信息成功，返回：' + JSON.stringify(streamerInfo))    
// }).catch(err => {
//   console.log('获取当前直播间主播信息失败，错误信息：' + err.message)
// })
// console.log("**********当前版本信息：",window.__os,window.__hyextInfo);
